import { getContext } from '@/context/common/applicationContext'
import React, { Component } from 'react'
import { Descriptions, DatePicker, Tag, ConfigProvider, Spin, message, List } from 'antd'
import InputWidget from '@/components/basicWidget/InputWidget'
import TextAreaWidget from '@/components/basicWidget/TextAreaWidget'
import {
    CheckCircleOutlined,
    ClockCircleOutlined,
    SyncOutlined, MinusCircleOutlined
} from '@ant-design/icons'
import zh_CN from 'antd/es/locale/zh_CN'
import { TableButton } from '@/components/basicWidget/Button'
import { withRouterContext } from '@/context/router/routerContext'
import { get, getText, post } from '@/utils/requestUtil'
import moment from 'moment'

class WeiboCrawl extends Component {

    state = {
        loading: true,
        taskName: null,
        taskInfo: {
            taskContent: {
                taskName: null,
                params: {}
            }
        },
        intervalId: null, //定时任务id
    }

    async componentDidMount() {
        let taskName = this.props.searchParams[0].get('taskName')
        let taskInfo = {
            taskContent: {
                taskName: null,
                params: {}
            }
        }
        let intervalId = null
        if (taskName) {
            const response = await get(`/crawl/get/status?taskName=${taskName}`)
            if (response && response.code === 200) {
                taskInfo = response.data
                taskInfo.taskContent = JSON.parse(taskInfo.taskContent)
                if (taskInfo.taskStatus !== 'END') {
                    intervalId = setInterval(this.getTaskStatus, 1000 * 60)
                }
            }
        }
        await new Promise(resolve => {
            this.setState({
                loading: false,
                taskName,
                taskInfo,
                intervalId
            }, resolve)
        })
    }

    async componentWillUnmount() {
        if (this.state.intervalId) {
            clearInterval(this.state.intervalId)
        }
    }

    async shouldComponentUpdate(nextProps, nextState) {
        if (this.props.searchParams[0].get('taskName') !== nextProps.searchParams[0].get('taskName')) {
            //清理定时器
            if (this.state.intervalId) {
                clearInterval(this.state.intervalId)
            }
            //重新赋值
            let taskName = nextProps.searchParams[0].get('taskName')
            let taskInfo = {
                taskContent: {
                    taskName: null,
                    params: {}
                }
            }
            let intervalId = null
            if (taskName) {
                const response = await get(`/crawl/get/status?taskName=${taskName}`)
                if (response && response.code === 200) {
                    taskInfo = response.data
                    taskInfo.taskContent = JSON.parse(taskInfo.taskContent)
                    if (taskInfo.taskStatus !== 'END') {
                        intervalId = setInterval(this.getTaskStatus, 1000 * 60)
                    }
                }
            }
            await new Promise(resolve => {
                this.setState({
                    taskName,
                    taskInfo,
                    intervalId
                }, resolve)
            })
        }
        return true
    }

    getTaskStatus = async () => {
        const { taskName } = this.state
        if (taskName) {
            const response = await get(`/crawl/get/status?taskName=${taskName}`)
            if (response && response.code === 200) {
                let taskInfo = response.data
                taskInfo.taskContent = JSON.parse(taskInfo.taskContent)
                await new Promise(resolve => {
                    this.setState({
                        taskInfo
                    }, resolve)
                })
                if (taskInfo.taskStatus === 'END' && this.state.intervalId) {
                    clearInterval(this.state.intervalId)
                }
            }
        }
    }

    onChange = (fieldName) => {
        return async (value) => {
            await new Promise((resolve) => {
                this.setState({
                    [fieldName]: value
                }, resolve)
            })
        }
    }

    onDateChange = (fieldName) => {
        return async (date, dateString) => {
            await new Promise((resolve) => {
                this.setState({
                    [fieldName]: dateString
                }, resolve)
            })
        }
    }

    //开始爬取操作
    startCrawl = async () => {
        const { code, cookies, start_date, end_date } = this.state
        let validate = true
        if (!code) {
            validate = false
            message.warning('爬取关键词不能为空')
        }
        if (!cookies) {
            validate = false
            message.warning('个人cookie不能为空')
        }
        if (!start_date) {
            validate = false
            message.warning('开始日期不能为空')
        }
        if (!end_date) {
            validate = false
            message.warning('结束日期不能为空')
        }
        if (!validate) return false
        const response = await post('/crawl/start/weibo', {
            body: JSON.stringify({
                code, cookies, start_date, end_date
            })
        })
        if (response && response.code === 200) {
            message.success(response.message)
            let taskName = response.data
            let taskInfo = null
            let intervalId = null
            const response1 = await get(`/crawl/get/status?taskName=${taskName}`)
            if (response1 && response1.code === 200) {
                taskInfo = response1.data
                taskInfo.taskContent = JSON.parse(taskInfo.taskContent)
                if (taskInfo.taskStatus !== 'END') {
                    intervalId = setInterval(this.getTaskStatus, 1000 * 60)
                }
                await new Promise(resolve => {
                    this.setState({
                        taskName,
                        taskInfo,
                        intervalId
                    }, resolve)
                })
            }
        }
    }

    //停止爬取操作
    stopCrawl = async () => {
        const response = await post(`/crawl/stop?taskName=${this.state.taskName}`)
        if (response && response.code === 200) {
            //清除定时器
            if (this.state.intervalId) {
                clearInterval(this.state.intervalId)
            }
            if (this.state.taskInfo.taskStatus === 'WAITING') {
                message.success('本次爬取已取消')
                //恢复初始状态
                let taskName = null
                let taskInfo = {
                    taskContent: {
                        taskName: null,
                        params: {}
                    }
                }
                let intervalId = null
                await new Promise(resolve => {
                    this.setState({
                        taskName,
                        taskInfo,
                        intervalId
                    }, resolve)
                })
            } else if (this.state.taskInfo.taskStatus === 'RUNNING') {
                message.success('操作成功，正在结束爬取，请耐心等候...')
                while (this.state.taskInfo.taskStatus !== 'END') {
                    //每10秒循环一次，检查状态
                    await this.getTaskStatus()
                    await new Promise(resolve => {
                        setTimeout(() => {
                            resolve()
                        }, 1000 * 10)
                    })
                }
            }
        }
    }

    render() {
        if (this.state.loading === true) return <Spin />
        const taskInfo = this.state.taskInfo
        const taskContent = taskInfo.taskContent
        const params = taskContent.params
        const items = [
            { key: 'taskType', label: '服务类型', children: '微博平台数据爬取', span: 1.5 },
            { key: 'taskName', label: '服务名称', children: taskContent.taskName || '', span: 1.5 },
            {
                key: 'code', label: '爬取关键词（多个关键词以“,”分隔）', span: 3,
                children: taskInfo.taskStatus ? params.important_codes.join(',') :
                    <InputWidget onChange={this.onChange('code')} />
            },
            {
                key: 'cookies', label: '个人cookie', span: 3,
                children: taskInfo.taskStatus ? params.cookies :
                    <TextAreaWidget resize={false} onChange={this.onChange('cookies')} />
            },
            {
                key: 'start_date', label: '开始日期', span: 1.5,
                children: taskInfo.taskStatus ? moment(params.start_date).format('yyyy-MM-DD') :
                    <DatePicker onChange={this.onDateChange('start_date')} />
            },
            {
                key: 'end_date', label: '结束日期', span: 1.5,
                children: taskInfo.taskStatus ? moment(params.end_date).format('yyyy-MM-DD') :
                    <DatePicker onChange={this.onDateChange('end_date')} />
            },
        ]
        let title
        if (taskInfo.taskStatus === 'END') {
            title = <span>
                微博平台数据爬取&nbsp;&nbsp;&nbsp;&nbsp;
                <Tag icon={<CheckCircleOutlined />} color='success'>success</Tag>
            </span>
        } else if (taskInfo.taskStatus === 'RUNNING') {
            title = <span>
                微博平台数据爬取&nbsp;&nbsp;&nbsp;&nbsp;
                <Tag icon={<SyncOutlined spin />} color='processing'>running</Tag>
            </span>
        } else if (taskInfo.taskStatus === 'WAITING') {
            title = <span>
                微博平台数据爬取&nbsp;&nbsp;&nbsp;&nbsp;
                <Tag icon={<ClockCircleOutlined />} color='warning'>waiting</Tag>
            </span>
        } else {
            title = <span>
                微博平台数据爬取&nbsp;&nbsp;&nbsp;&nbsp;
                <Tag icon={<MinusCircleOutlined />} color="default">no-start</Tag>
            </span>
        }

        //组装爬取结果
        let result = []
        if (taskInfo.taskStatus === 'END') {
            const { comment_csv_filePaths, content_csv_filePaths } = params
            result = [...comment_csv_filePaths, ...content_csv_filePaths]
        }

        return (
            <ConfigProvider locale={zh_CN}>
                <Descriptions title={title} bordered items={items} layout='vertical' size='small'/>
                <div style={{ position: 'absolute', top: '15px', right: '20px' }}>
                    {
                        !taskInfo.taskStatus ?
                            <TableButton
                                style={{ backgroundColor: 'rgb(22, 119, 255)', marginRight: '10px' }}
                                onClick={this.startCrawl}
                            >开始爬取</TableButton> : ''
                    }
                    {
                        taskInfo.taskStatus === 'RUNNING' || taskInfo.taskStatus === 'WAITING' ?
                            <TableButton
                                style={{ backgroundColor: 'rgb(22, 119, 255)' }}
                                onClick={this.stopCrawl}
                            >
                                {taskInfo.taskStatus === 'RUNNING' ? '结束爬取' : '放弃等待'}
                            </TableButton> : ''
                    }
                </div>
                {
                    taskInfo.taskStatus !== 'END' ? '' :
                        <List
                            style={{ marginTop: 10 }}
                            header={<div>结果列表</div>}
                            dataSource={result}
                            bordered
                            size='small'
                            renderItem={(item) => {
                                let textArray = item.split('/')
                                let fileName = textArray[textArray.length - 1]
                                return (
                                    <List.Item
                                        actions={[<TableButton style={{ backgroundColor: 'rgb(22, 119, 255)' }} onClick={async () => {
                                            const response = await getText(`/crawl/downloadCrawlFile?fileName=${fileName}`)
                                            let file = new File([response], fileName, {
                                                type: "text/csv",
                                            });
                                            let tmpLink = document.createElement("a");
                                            let objectUrl = URL.createObjectURL(file);
                            
                                            tmpLink.href = objectUrl;
                                            tmpLink.download = file.name;
                                            document.body.appendChild(tmpLink);
                                            tmpLink.click();
                            
                                            document.body.removeChild(tmpLink);
                                            URL.revokeObjectURL(objectUrl);
                                        }}>下载</TableButton>]}
                                    >
                                        {fileName}
                                    </List.Item>
                                )
                            }}
                        >
                        </List>
                }
            </ConfigProvider>
        )
    }
}

export default withRouterContext(getContext(WeiboCrawl))